/**
 * 
 */
package geral.phaselistener;

import java.util.ArrayList;
import java.util.List;

import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

import seguranca.helper.SegurancaManagerHelper;
import seguranca.manager.SegurancaManager;



public class LoginPhaseListener implements PhaseListener {
        /** Serial Version UID. */
        private static final long serialVersionUID = 8403402696846718508L;

        /**
         * Padroes de Excecoes.
         */
        private static final List<String> EXCECOES = new ArrayList<String>();

        /**
         * Excecões para o PhaseLister. O Filtro de Login não restringe o acesso as
         * páginas abaixo.
         */
        {
                EXCECOES.add(".xcss");
                EXCECOES.add("/login.xhtml");
                EXCECOES.add("/paginas/primeiroAcesso.xhtml");
        }

        /**
         * Verifica se o usuario esta logado no sistema.
         * 
         * @param event
         *            {@link PhaseEvent}
         * @see PhaseListener#beforePhase(PhaseEvent)
         */
        public void afterPhase(PhaseEvent event) {
                FacesContext context = event.getFacesContext();
                String viewId = context.getViewRoot().getViewId();
                SegurancaManager usuarioBean = SegurancaManagerHelper.getSegurancaManager();
                String[] path = viewId.split("/");
                usuarioBean.setModulo(path.length > 2 ? path[2] : "");
                
                if (context.getViewRoot() != null) {
                    viewId = context.getViewRoot().getViewId();
                }

                //Verifica se há usuario authenticado
                if (event.getPhaseId().equals(PhaseId.RESTORE_VIEW)) {
                    if (context.getExternalContext().getSession(false) == null) {
                        System.out.println("sessionExpired");
                        navigateToView(context, "login");
                    // /public/login.jsf
                    }

                    if (!isExcecao(viewId) && (usuarioBean.getUsuarioLogado() == null || usuarioBean.getUsuarioLogado().getId() == null)) {
                        navigateToView(context, "login");
                    }
                }

                if (event.getPhaseId().equals(PhaseId.APPLY_REQUEST_VALUES)) {
                    if (viewId.contains("/logout.") || viewId.contains("/login.")) {
                        usuarioBean.logout();
                    } else if (!isExcecao(viewId) && (usuarioBean.getUsuarioLogado() == null || usuarioBean.getUsuarioLogado().getId() == null)) {
                        navigateToView(context, "login");
                    }
                }
                
        }

        /**
         * Navega para um view.
         * 
         * @param context
         *            Faces Context atrelado a requisição atual.
         * @param view
         *            outcome para qual se deseja navegar
         */
        private void navigateToView(FacesContext context, String view) {
                Application application = context.getApplication();
                NavigationHandler navigationHandler = application.getNavigationHandler();
                navigationHandler.handleNavigation(context, null, view);
        }

        /**
         * Identifica se uma página e execao ao controle de acesso.
         * 
         * @param viewId
         * @return Verdadeiro
         */
        private boolean isExcecao(String viewId) {
                for (String view : EXCECOES) {
                        if (viewId.indexOf(view) >= 0) {
                                return true;
                        }
                }
                return false;
        }

        /**
         * Metodo da interface PhaseListener. Nao utilizado.
         * 
         * @param event
         *            {@link PhaseEvent}
         * @see PhaseListener#beforePhase(PhaseEvent)
         */
        public void beforePhase(PhaseEvent event) {

        }

      
        @Override
        public PhaseId getPhaseId() {
        	return PhaseId.RESTORE_VIEW;
        }
}